package com.douqu.game.core.entity.world;

import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.config.FunctionConfig;
import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.config.battle.MonsterConfig;
import com.douqu.game.core.config.card.CardConfig;
import com.douqu.game.core.config.challenge.CardParamConfig;
import com.douqu.game.core.config.challenge.WorldBossConfig;
import com.douqu.game.core.config.challenge.WorldBossParameterConfig;
import com.douqu.game.core.config.sprite.MasterParamConfig;
import com.douqu.game.core.e.E_Attribute;
import com.douqu.game.core.e.E_StableDataType;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.battle.SpriteTemp;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.db.CardDB;
import com.douqu.game.core.entity.ext.data.BaseData;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.FunctionFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.StringUtils;
import com.douqu.game.core.util.time.TimeUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

/**
 * @Author: zhenfei
 * @Description: 世界Boss信息
 * @Date: 2018-02-06 10:53
 */
public class WorldBossData extends BaseData {

    /**
     * 记录本周已经击杀的boss
     */
    private List<String> hasKillBoss;
    /**
     * 当前boss信息
     */
    private BattleTemp bossInfo;
    /**
     * boss结束时间
     */
    private long endTime; // 0表示boss已被击毙

    /**
     * boss死亡时间
     *
     * 当发放过奖励设置成0
     * 当boss死亡设置死亡时间
     */
    private long deathTime;

    /**
     * 当前的玩家平均等级等级
     */
    private int lv;

    /**
     * 获取的玩家等级
     */
    private int averageLv;

    /**
     * 上一次的刷新时间
     */
    private long lastFreshTime;


    public WorldBossData()
    {
        bossInfo = new BattleTemp();
        hasKillBoss = new CopyOnWriteArrayList<>();

        FunctionConfig config = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, FunctionFactory.WORLD_BOSS);
        if(config != null){
            averageLv = config.lv + 1;
        }
    }

    @Override
    public void init() {

    }


    @Override
    public void checkInit() {
        init();
    }

    /**
     * 一周reset一次
     */
    @Override
    public void reset() {
        lastFreshTime = DataFactory.currentTime;
        hasKillBoss.clear();
    }

    @Override
    public void checkReset() {
        if(!CoreUtils.isSameWeek(DataFactory.currentTime, lastFreshTime)){
            reset();
        }
    }

    @Override
    public void writeTo(ByteBuffer buffer)
    {
        buffer.writeShort(hasKillBoss.size());
        for(String id : hasKillBoss){
            buffer.writeUTF(id);
        }

        buffer.writeLong(deathTime);
        if(isCanCreeateBoss()){
            buffer.writeUTF("");
        }else {
            buffer.writeUTF(bossInfo.getIndexInfo());
            bossInfo.writeTo(buffer);
            buffer.writeLong(endTime);
        }

    }

    @Override
    public void loadFrom(ByteBuffer buffer) {
        int size = buffer.readShort();
        hasKillBoss.clear();
        for(int i = 0; i < size; i++){
            hasKillBoss.add(buffer.readUTF());
        }

        //***********************旧的
//        boolean flag = buffer.readBoolean();
//        if(flag)
//            buffer.readUTF();
        //***********************

        //------------------------新的
        deathTime = buffer.readLong();

        bossInfo.setIndexInfo(buffer.readUTF());
        if (!StringUtils.isNullOrEmpty(bossInfo.getIndexInfo())) {
            bossInfo.loadForm(buffer);
            endTime = buffer.readLong();
        }
        //--------------------------
    }

    public boolean isSameBoss(int bossId){
        return String.valueOf(bossId).equals(bossInfo.getIndexInfo());
    }

    /**
     * 创建一个新的Boss
     *
     * @param bossId
     */
    public boolean createNewBoss(int bossId, int averageLv) {
        synchronized (this){
//            if(isSameBoss(bossId)){
//                return false;
//            }
            lv = averageLv;
            LogUtils.warn("创建BOSS， id:" + bossId + ", lv:" + averageLv);
            //battlePlayers.clear();
            WorldBossConfig bossConfig = changeBossInfo(bossId);
            endTime = DataFactory.currentTime + bossConfig.freshTime.getKeepTime(TimeUtils.MILLISECOND);

            bossInfo.getCurrentTotalHp();
            bossInfo.getMaxTotalHp();
            lastFreshTime = DataFactory.currentTime;
            return true;
        }

    }

    private WorldBossConfig changeBossInfo(int bossId) {
        WorldBossConfig bossConfig = DataFactory.getInstance().getGameObject(DataFactory.WORLD_BOSS_KEY, bossId);
        StableDataConfig stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.BOSS_ID_OFFSET.getCode());
        int offset = stableDataConfig == null ? 0 : stableDataConfig.intValue;
        MasterParamConfig masterParamConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_PARAM_KEY, lv + offset);
        long maxHp = (long) (masterParamConfig.hp * bossConfig.getExtRate(E_Attribute.HP));
        bossInfo = new BattleTemp();
        bossInfo.setIndexInfo(bossConfig.getId() + "");
        bossInfo.setMaster(new SpriteTemp(bossConfig.master, lv, maxHp, maxHp, maxHp, 0));
        bossInfo.setStar(lv);
        WorldBossParameterConfig parameterConfig = DataFactory.getInstance().getGameObject(DataFactory.WORLD_BOSS_PARAM_KEY, lv);
        MonsterConfig monsterConfig = DataFactory.getInstance().getGameObject(DataFactory.MONSTER_KEY, bossConfig.monsterId);
        CardDB cardDB;
        bossInfo.getSoldierList().clear();
        if (monsterConfig != null) {
            int index = 0;
            // 获得怪物属性配置
            int[] cardParam;
            boolean isNullCardParam = monsterConfig.isNullCardParam();
            CardConfig cardConfig;
            for (int i = 0; i < monsterConfig.cards.length; i++) {
                cardConfig = monsterConfig.cards[i];
                cardDB = new CardDB(cardConfig.id, null);
                if (!isNullCardParam) {
                    int cardParamId = monsterConfig.cardParam[i];
                    CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, cardParamId);
                    cardParam = cardParamConfig.cardParams;
                    cardDB.setMonsterData(cardParam);
                    cardDB.setExtAttr(cardParamConfig.paraments);

                } else {
                    cardParam = parameterConfig.monsterLv;
                    cardDB.setMonsterData(cardParam);
                    //boss没有附加属性
                    cardDB.setExtAttr(null);
                }
                maxHp = (long) (cardDB.getAttribute(E_Attribute.HP.getCode()) * bossConfig.getExtRate(E_Attribute.HP));
                bossInfo.addSoldierTemp(new SpriteTemp(cardDB.id, cardDB.getLv(), maxHp, maxHp, maxHp, index++), false);
            }
        }

        return bossConfig;
    }

    /**
     * 击杀boss
     * 返回true表示真的killboss了 返回false表示boss被别人kill了
     * @param bossId
     */
    public boolean killBoss(String bossId) {
        synchronized (this) {
            LogUtils.warn("boss死亡 bossId:" + bossId);
            //如果deathTime 不是0 则表示刚刚击杀过boss不可再击杀
            if (bossInfo != null && bossInfo.getIndexInfo().equals(bossId) && endTime != 0 && deathTime == 0) {
                endTime = 0;
                hasKillBoss.add(bossId);
                //boss的死亡设置boss死亡时间
                deathTime = DataFactory.currentTime;
                return true;
            }
        }
        return false;
    }

    /**
     * 伤害直接存在排行榜上 这里不再进行统计
     * 增加玩家挑战记录 和增加的伤害值
     * 在战斗发起成功的时候需要调用一次，damage传0， 在战斗结束再调用一次，damage传递真实伤害值
     */
//    public void addChallengeRecord(String objectIndex, String bossId, long damage) {
//        if (bossInfo != null &&
//                bossInfo.getIndexInfo().equals(bossId)) {
//            battlePlayers.put(objectIndex, value);
//        }
//    }

    public boolean isCanCreeateBoss(){
        //boss被杀死
        if (!isBossActive()){
            //并且发放过奖励
            if (deathTime == 0){
                return true;
            }
        }
        return false;
    }

    /**
     * BOSS是否活跃
     *
     * @return
     */
    public boolean isBossActive() {
        if (endTime == 0){
            return false;
        }

        if (StringUtils.isNullOrEmpty(bossInfo.getIndexInfo())){
            return false;
        }

        return true;
    }


    /**
     * 刷新boss血量
     * 返回true 表示boss死亡
     * @param battleTemp
     */
    public boolean freshBossHp(BattleTemp battleTemp) {


        if(battleTemp == null){
            return false;
        }
        if(endTime == 0){
            return false;
        }

        if(!battleTemp.getIndexInfo().equals(bossInfo.getIndexInfo())){
            return false;
        }

        synchronized (this){
            bossInfo.getMaster().setHp(bossInfo.getMaster().getHp() - ((battleTemp.getMaster().getCacheMaxHp()) -  battleTemp.getMaster().getHp()));
            if(bossInfo.getMaster().getHp() <= 0){
                return killBoss(battleTemp.getIndexInfo());
            }
            List<SpriteTemp> soldierList = bossInfo.getSoldierList();
            for(SpriteTemp soldier : soldierList)
            {
                SpriteTemp temp = battleTemp.getSpriteTemp(soldier.getId(), soldier.getIndex());
                long offset = temp.getCacheMaxHp() - temp.getHp();
                soldier.setHp(Math.max(0,soldier.getHp() - offset));
            }
        }

        return false;
    }

    /**
     * 计算伤害转化数值
     * @param battleTemp
     */
    public TwoTuple<Integer, String> calculateDamageRate(BattleTemp battleTemp) {

        if(battleTemp == null){
            return new TwoTuple(1, "battleTemp-Null");
        }
        //20180803 修改为无论BOSS是否死亡都给玩家功勋
//        if(endTime == 0){
//            return new TwoTuple(1, "Boss-Died");
//        }

        long sum = battleTemp.getTotalDamage();

        WorldBossParameterConfig config = DataFactory.getInstance().getGameObject(DataFactory.WORLD_BOSS_PARAM_KEY, lv);
        if(config == null){
            config = (WorldBossParameterConfig) DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_PARAM_KEY).get(0);
        }
        sum = sum / config.translateRate;
        LogUtils.info("造成伤害:" + sum + ", 伤害转化率:" + config.translateRate);
        return new TwoTuple((int)(sum <= 0 ? 1 : sum), "sum/translateRate=" + sum + "/" + config.translateRate);
    }


    public BattleTemp getBossInfo() {
        return bossInfo;
    }

    public List<String> getHasKillBoss() {
        return hasKillBoss;
    }

    public List<Integer> getHasKillBossIntValue() {
        List<Integer> list = new ArrayList<>();
        for (String id : hasKillBoss) {
            list.add(Integer.valueOf(id));
        }
        return list;
    }



    public int getNextBossId(long startTime) {
        List<WorldBossConfig> list = DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_KEY);
        for(WorldBossConfig config : list){
            if(config.isUnTouchTime(startTime)){
                return config.id;
            }
        }
        return 0;
    }

    public long getEndTime() {
        return endTime;
    }

    public void setEndTime(int endTime) {
        this.endTime = endTime;
    }

    public int getLv() {
        return lv;
    }

    public long getDeathTime() {
        return deathTime;
    }

    public void setDeathTime(long deathTime) {
        this.deathTime = deathTime;
    }

    public void bossOutTime(){
        synchronized (this){
            LogUtils.warn("boss截止时间到");
            this.endTime = 0;
        }
    }

    public TwoTuple<SGCommonProto.E_BOSS_STATE,Integer> bossState(){
        TwoTuple<SGCommonProto.E_BOSS_STATE,Integer> twoTuple = new TwoTuple<>();
        //判断当前是否有boss或者
        if (endTime > 0){
            twoTuple.setFirst(SGCommonProto.E_BOSS_STATE.BOSS_STATE_ING);
            return twoTuple;
        }
        //判断今日还有boss没
        List<WorldBossConfig> bossConfigList = DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_KEY);
        //
        int week = CoreUtils.getWeek();
        int hour = CoreUtils.getHour();
        AtomicInteger id = new AtomicInteger(0);
        bossConfigList.forEach((config)->{
           if (config.freshTime.timeArray[0] == week
                && config.freshTime.timeArray[1] > hour){
               id.set(config.id);
           }
        });
        if (id.get() != 0){
            twoTuple.setFirst(SGCommonProto.E_BOSS_STATE.BOSS_STATE_NOT_OPEN);
            twoTuple.setSecond(id.get());
            return twoTuple;
        }
        twoTuple.setFirst(SGCommonProto.E_BOSS_STATE.BOSS_STATE_END);
        return twoTuple;
    }

    public int getBossCountDown(){
        if (endTime == 0)
            return 0;

        int countDown = (int)(endTime - DataFactory.currentTime);
        if (countDown < 0){
            return 0;
        }
        return countDown;
    }

    public int getAverageLv() {
        return averageLv;
    }

    public void setAverageLv(int averageLv) {
        this.averageLv = averageLv;
    }
}
